package com.bdilab.redisexperiment.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
@CrossOrigin
@RequestMapping("/experiment")
public class RedisController {

    static String SHELL_PATH = "/home/redis-experiment/redis.sh";

    @ResponseBody
    @RequestMapping(value = "/redis",method = RequestMethod.GET)
    public String redis(@RequestParam(required = false) Integer replBacklogSize,
                        @RequestParam(required = false)Integer hashMaxZiplistValue,
                        @RequestParam(required = false)Integer hashMaxZiplistEntries,
                        @RequestParam(required = false)Integer listMaxZiplistSize,
                        @RequestParam(required = false)Integer activeDefragIgnoreBytes,
                        @RequestParam(required = false)Integer activeDefragThresholdLower,
                        @RequestParam(required = false)String replDisableTcpNodelay,
                        @RequestParam(required = false)Integer hllSparseMaxBytes,
                        @RequestParam(required = false)Integer hz){
        //获取redis的九个参数值
        //调用redis的benchmark跑数据，拿到结果
        //处理结果，得到QPS，返回给python端

        //http://localhost:8080/experiment/redis?replBacklogSize=10&hashMaxZiplistValue=60&hashMaxZiplistEntries=862&listMaxZiplistSize=3&activeDefragIgnoreBytes=162&activeDefragThresholdLower=15&replDisableTcpNodelay=no&hllSparseMaxBytes=11398&hz=22
        List<String> params = new ArrayList<>();
        params.add(SHELL_PATH);
        params.add(replBacklogSize == null ? "1" : replBacklogSize.toString());
        params.add(hashMaxZiplistValue == null ? "64" : hashMaxZiplistValue.toString());
        params.add(hashMaxZiplistEntries == null ? "512" : hashMaxZiplistEntries.toString());
        params.add(listMaxZiplistSize == null ? "-2" : listMaxZiplistSize.toString());
        params.add(activeDefragIgnoreBytes == null ? "100" : activeDefragIgnoreBytes.toString());
        params.add(activeDefragThresholdLower == null ? "10" : activeDefragThresholdLower.toString());
        params.add(replDisableTcpNodelay == null ? "no" : replDisableTcpNodelay);
        params.add(hllSparseMaxBytes == null ? "3000" : hllSparseMaxBytes.toString());
        params.add(hz == null ? "10" : hz.toString());

        ProcessBuilder processBuilder = new ProcessBuilder(params);
        // 通知进程生成器是否合并标准错误和标准输出
        // 默认为false，此时子进程的标准输出和错误输出会被发给两个独立的流，需要通过Process.getInputStream()和Process.getErrorStream()来访问
        // 如果设置为true，标准错误和标准输出合并，从 Process.getInputStream()获取
        processBuilder.redirectErrorStream(true);
        String result = "";
        try {
            // 有两种方法创建Process对象，ProcessBuilder.start() 和 Runtime.exec()，两者的参数不同。
            // 通过查看JDK源码可知，Runtime.exec最终是通过调用ProcessBuilder来真正执行操作的。
            Process process = processBuilder.start();
            InputStream is = process.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line;
            while ((line = br.readLine())!=null){
                System.out.println(line);
                if (line.contains("requests per second"))
                result = line.split(" ")[1];
            }
            //waitFor()：导致当前线程等待，如果必要，一直要等到由该 Process 对象表示的进程已经终止。
            //runningStatus=0时正常
            int runningStatus = process.waitFor();
            System.out.println("runningStatus=" + runningStatus);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("currentTime=" + sdf.format(new Date()));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result;
    }

    @ResponseBody
    @GetMapping()
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String hello(){
        return "helloworld";
    }
}
